#include <pthread.h>
#include <unistd.h>
#include <cstdio>
#include <vector>
#include <iostream>
#include <string>
#include "thread.hpp"

using namespace std;

const int NUM = 5;

pthread_mutex_t* lock = new pthread_mutex_t(PTHREAD_MUTEX_INITIALIZER);

vector<pthread_t> threads;

class thread
{
public:
    thread(string thread_no, pthread_mutex_t* lock)
        :_thread_no(thread_no),
        _lock(lock)
    {}

    thread(int thread_no, pthread_mutex_t* lock)
        :_thread_no(to_string(thread_no)), 
        _lock(lock)
    {}

public:
    string _thread_no;
    pthread_mutex_t* _lock;
};

// //线程层面的全局变量
// __thread int n = 10; //__thread 选项

// void* check(void* args)
// {
//     thread* td = static_cast<thread*>(args);
//     ++n;
//     cout << "thread-" << td->_thread_no << ":" << n << endl;
//     usleep(1000);
//     // int num = 0;
//     // for(int i = 0; i < 5; ++i)
//     // {
//     //     cout << "thread-" << td->_thread_no << ":" << num << endl;
//     //     ++num;
//     //     usleep(50000);
//     // }
//     return nullptr;
// }

int tickets = 1000;

// void* getTickets(void* args)
// {
//     thread* td = static_cast<thread*>(args);
//     lock* mylock = new lock(td->_lock);
//     while(true)
//     {
//         {
//             lockguard lock(mylock); //RAII 风格的锁
//             if(tickets > 0)
//             {
//                 usleep(1000);
//                 --tickets;
//                 printf("%s get a ticket, tickets: %d\n", td->_thread_no.c_str(), tickets);
//             }
//             else {
//                 break;
//             }
//         }
//         usleep(100); //进行一轮抢票后，不会立即进行下一轮抢票，还需要进行收尾工作
//     }
// }

void* getTickets(void* args)
{
    thread* td = static_cast<thread*>(args);
    while(true)
    {
        pthread_mutex_lock(td->_lock);
        if(tickets > 0)
        {
            usleep(1000);
            --tickets;
            printf("%s get a ticket, tickets: %d\n", td->_thread_no.c_str(), tickets);
        }
        else {
            pthread_mutex_unlock(td->_lock);
            break;
        }
        pthread_mutex_unlock(td->_lock);
        usleep(100); //进行一轮抢票后，不会立即进行下一轮抢票，还需要进行收尾工作
    }
}

int main()
{
    //pthread_mutex_t* lock = new pthread_mutex_t;
    //pthread_mutex_init(lock, nullptr);
    for(int i = 0; i < NUM; ++i)
    {
        thread* td = new thread(i, lock);
        pthread_t newThread;
        pthread_create(&newThread, nullptr, getTickets, (void*)td);
        threads.push_back(newThread);
        //usleep(1000);
    }
    for(auto thread : threads) {
        pthread_join(thread, nullptr);
    }
    //pthread_mutex_destroy(lock);
    return 0;
}